/*
 * Copyright (C) Cátedra SAES-UMU 2011 <pedromateo@um.es>
 *
 * Android HCI Extractor is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Android HCI Extractor is distributed in the hope that it will be
 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.mmi.android.instrumentation.filters;

import org.mmi.android.instrumentation.BaseFilter;
import org.mmi.android.instrumentation.sentinel.SentinelView;
import org.mmi.android.instrumentation.sentinel.listeners.OnWindowVisibilityChangedListener;
import org.mmi.android.instrumentation.utils.UiTraverser;
import org.mmi.android.instrumentation.viewproxies.BaseViewProxy;
import org.mmi.android.instrumentation.viewproxies.ButtonProxy;
import org.mmi.android.instrumentation.viewproxies.CheckBoxProxy;
import org.mmi.android.instrumentation.viewproxies.EditTextProxy;
import org.mmi.android.instrumentation.viewproxies.ListViewProxy;
import org.mmi.android.instrumentation.viewproxies.ProgressBarProxy;
import org.mmi.android.instrumentation.viewproxies.RadioButtonProxy;
import org.mmi.android.instrumentation.viewproxies.RadioGroupProxy;
import org.mmi.android.instrumentation.viewproxies.RatingBarProxy;
import org.mmi.android.instrumentation.viewproxies.SeekBarProxy;
import org.mmi.android.instrumentation.viewproxies.SpinnerProxy;
import org.mmi.android.instrumentation.viewproxies.TextViewProxy;
import org.mmi.android.instrumentation.viewproxies.ViewProxyManager;
import org.mmi.android.instrumentation.viewproxies.ViewProxyManager.ProxyConflictException;
import org.mmi.facades.BaseMmiFacade;

import android.content.DialogInterface;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View;
import android.view.View.OnCreateContextMenuListener;
import android.view.View.OnFocusChangeListener;
import android.widget.AdapterView;
/* FIXME uncomment if API 11 or higher
import android.view.View.OnLayoutChangeListener;
import android.view.View.OnSystemUiVisibilityChangeListener;
*/

public class ViewChangesFilter
extends BaseFilter
implements OnFocusChangeListener,
/* FIXME uncomment if API higher than 4
OnShowListener,
*/
OnCreateContextMenuListener,

/* FIXME uncomment if API 11 or higher
OnLayoutChangeListener,
OnSystemUiVisibilityChangeListener,
*/

/* FIXME uncomment if API 12 or higher
//OnAttachStateChangeListener, API 12
*/
OnWindowVisibilityChangedListener
{

	private static final String TAG = "ViewChangesFilter";

	/**
	 * Constructor
	 */
	public ViewChangesFilter(BaseMmiFacade f){
		super(f);

		//initialize view proxies
		_initializeViewProxyManager();
	}

	///
	/// InteractionListener interface implementation
	///

	@Override
	public void onInteractionStart() {
		// TODO Auto-generated method stub

	}

	@Override
	public void onInteractionEnd() {
		// TODO Auto-generated method stub

	}

	///
	/// BaseFilter abstract methods implementation
	///

	public void install(View v)
	{
		try{
			if (v != null)
			{

				///
				/// only for SentinelView
				///
				if (v instanceof SentinelView){
					Log.v(TAG,"SentinelView :: Installing listeners");
					SentinelView sv = ((SentinelView)v);
					sv.setOnWindowVisibilityChangedListener(this);
				}

				///
				/// Only for AdapterView
				///
				if (v instanceof AdapterView){
					Log.v(TAG,"AdapterView :: Installing listeners");

				}

				///
				/// Only for not-AdapterView
				///
				else{
					Log.v(TAG,"View :: Installing listeners");
				}

				///
				/// for all views
				///
				//v.setOnFocusChangeListener(this);
				//v.setOnCreateContextMenuListener(this);
				/* FIXME uncomment if API 11 or higher
				v.setOnSystemUiVisibilityChangeListener(this);
				v.addOnLayoutChangeListener(this);
				*/

			}
			else{
				Log.w(TAG,"View is NULL");
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	///
	/// filtering methods
	///

	@Override
	public void onWindowVisibilityChange(SentinelView sv, int visibility) {
		//Log.v(TAG,"@@@@@@@@@@@@@@@@@@@@@@@@@ onWindowVisibilityChange " + visibility);
		if (visibility == View.VISIBLE){
			//get the top parent view of this GUI
			View topView = UiTraverser.getTopParent(sv);
			if (topView == null){
				Log.w(TAG,"onWindowVisibilityChange :: topView is null");
				return;
			}

			//traverse the GUI
			UiTraverser uit = new UiTraverser(topView);
			View auxv = null;
			while (uit.hasNext())
			{
				auxv = uit.next();
				if (auxv == null){
					Log.w(TAG,"onWindowVisibilityChange :: auxv is null");
					continue;
				}

				//for all proxyed Views...
				BaseViewProxy proxy = pmanager_.getProxy(auxv);
				if (proxy != null)
				{
					Log.v(TAG,"%%%% (view) " + auxv.toString());
					Log.v(TAG,"%%%% (elements) " + proxy.getElements(auxv));
					Log.v(TAG,"%%%% (concepts) " + proxy.getConcepts(auxv));
					Log.v(TAG,"%%%% (noise) " + proxy.getNoise(auxv));
					Log.v(TAG,"%%%% (is question) " + proxy.isQuestion(auxv));
					Log.v(TAG,"%%%% (is feedback) " + proxy.isFeedback(auxv));


					//...send information to interaction model
					int auxi;
					//set elements or feedback elements
					auxi = proxy.getElements(auxv);
					if (auxi > 0){
						if (proxy.isFeedback(auxv)){
							mmim_.newGuiFeedback(0,auxi);
						}
						else{
							mmim_.newGuiElements(0,auxi);
						}
					}
					//set concepts
					auxi = proxy.getConcepts(auxv);
					if (auxi > 0) mmim_.newGuiConcepts(0,auxi);
					//set noise
					auxi = proxy.getNoise(auxv);
					if (auxi > 0) mmim_.newGuiNoise(0,auxi);
					//set question
					if (proxy.isQuestion(auxv))
						mmim_.newGuiQuestions(0,1);
				}
			}

		}
	}

	/* FIXME uncomment if API 11 or higher
	 * @Override
	 */
	public void onSystemUiVisibilityChange(int arg0) {
		Log.d(TAG,"onSystemUiVisibilityChange");
	}

	/* FIXME uncomment if API 11 or higher
	 * @Override
	 */
	public void onLayoutChange(View arg0, int arg1, int arg2, int arg3,
			int arg4, int arg5, int arg6, int arg7, int arg8) {

		if (true) return;
		//1. if there is some real layout change, a new element appears
		//   if not, there are not new elements
		if (!(arg5 == 0 && arg6 == 0 &&
				arg7 == 0 && arg8 == 0)){
			return;
		}

		//2. we need to get a proxy and extract the information
		//   from views.
		//   elements without proxy are not taken into account
		if (pmanager_.getProxy(arg0) != null)
		{

			Log.d(TAG,"onLayoutChange" + " : " + arg0.toString() + " : " 
					+ arg1 + "."
					+ arg2 + "."
					+ arg3 + "."
					+ arg4 + "."
					+ arg5 + "."
					+ arg6 + "."
					+ arg7 + "."
					+ arg8
			);

			Log.d(TAG,"%%%% (elements) " + pmanager_.getProxy(arg0).getElements(arg0));
			Log.d(TAG,"%%%% (concepts) " + pmanager_.getProxy(arg0).getConcepts(arg0));
			Log.d(TAG,"%%%% (noise) " + pmanager_.getProxy(arg0).getNoise(arg0));
			Log.d(TAG,"%%%% (is question) " + pmanager_.getProxy(arg0).isQuestion(arg0));
			Log.d(TAG,"%%%% (is feedback) " + pmanager_.getProxy(arg0).isFeedback(arg0));

			///
			//send information to the framework
			int aux;
			//set elements or feedback elements
			aux = pmanager_.getProxy(arg0).getElements(arg0);
			if (aux > 0){
				if (pmanager_.getProxy(arg0).isFeedback(arg0)){
					mmim_.newGuiFeedback(0,aux);
				}
				else{
					mmim_.newGuiElements(0,aux);
				}
			}
			//set concepts
			aux = pmanager_.getProxy(arg0).getConcepts(arg0);
			if (aux > 0) mmim_.newGuiConcepts(0,aux);
			//set noise
			aux = pmanager_.getProxy(arg0).getNoise(arg0);
			if (aux > 0) mmim_.newGuiNoise(0,aux);
			//set question
			if (pmanager_.getProxy(arg0).isQuestion(arg0))
				mmim_.newGuiQuestions(0,1);
		}
	}

	@Override
	public void onCreateContextMenu(ContextMenu arg0, View arg1,
			ContextMenuInfo arg2) {
		Log.d(TAG,"onCreateContextMenu");
	}

	@Override
	public void onFocusChange(View arg0, boolean arg1) {
		Log.d(TAG,"onFocusChange" + " : " + arg0.toString());
	}

	/* FIXME uncomment if API higher than 4
	@Override
	*/
	public void onShow(DialogInterface arg0) {
		Log.d(TAG,"onShow" + " : " + arg0.toString());
	}

	///
	/// view proxies management
	///

	private ViewProxyManager pmanager_;

	private void _initializeViewProxyManager(){
		pmanager_ = new ViewProxyManager();

		//add different proxies
		try {
			pmanager_.addProxy(new ButtonProxy());
			pmanager_.addProxy(new CheckBoxProxy());
			pmanager_.addProxy(new EditTextProxy());
			pmanager_.addProxy(new ListViewProxy());
			pmanager_.addProxy(new ProgressBarProxy());
			pmanager_.addProxy(new RadioButtonProxy());
			pmanager_.addProxy(new RadioGroupProxy());
			pmanager_.addProxy(new RatingBarProxy());
			pmanager_.addProxy(new SeekBarProxy());
			pmanager_.addProxy(new SpinnerProxy());
			pmanager_.addProxy(new TextViewProxy());
		} catch (ProxyConflictException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
